import java.util.HashMap;

/**
 * Glados est notre calculateur, ou encore IA de la maison
 * @author smathomeutbm
 * @version 1.0
 */
public class Glados implements Runnable
{
    private HashMap<String,Capteur> listCapteur;
    private HashMap<String,Objet> listObjet;
    private HashMap<String,SourceEnergie> listEnergie;
    private int nbPiece;
    
	/**
     * Constructeur par défaut
     */
    public Glados() {
        listCapteur = new HashMap<String, Capteur>();
        listObjet = new HashMap<String, Objet>();
        listEnergie = new HashMap<String, SourceEnergie>();
        nbPiece = 0;
    }
    
	/**
     * Constructeur avec paramètres
     * @param capteur Liste des capteurs
     * @param objet Liste des objets
     * @param energie Liste des énergies
     * @param n Nombre de pièces dans la maison
     */
    public Glados(HashMap<String,Capteur> capteur, HashMap<String,Objet> objet, HashMap<String,SourceEnergie> energie, int n){
        listCapteur = capteur;
        listObjet = objet;
        listEnergie = energie;
        nbPiece = n;
    }
    
	/**
     * Rajouter un capteur à la liste des capteurs
     * @param capteur Capteur à rajouter à la liste
     */
    public void putCapteur(Capteur capteur) {
        listCapteur.put(capteur.getNomCapteur(),capteur);
    }
    
	/**
     * Rajouter un objet à la liste des objets
     * @param objet Objet à rajouter à la liste
     */
    public void putObjet(Objet objet){
        listObjet.put(objet.getNomObjet(),objet);
    }
    
	/**
     * Rajouter une énergie à la liste des énergies
     * @param energie Energie à rajouter à la liste
     */
    public void putEnergie(SourceEnergie energie){
        listEnergie.put(energie.getNomEnergie(),energie);
    }
    
	/**
     * Récupérer un capteur grâce à son nom
     * @param nomCapteur Nom du capteur à rechercher
     * @return Capteur dont le nom est passé en paramètre
     */
    public Capteur getCapteur(String nomCapteur){
        return listCapteur.get(nomCapteur);
    }
    
	/**
     * Récupérer un objet grâce à son nom
     * @param nomObjet Nom de l'objet à rechercher
     * @return Objet dont le nom est passé en paramètre
     */
    public Objet getObjet(String nomObjet) {
        return listObjet.get(nomObjet);
    }
    
	/**
     * Récupérer une énergie grâce à son nom
     * @param nomEnergie Nom de l'énergie à rechercher
     * @return SourceEnergie dont le nom est passé en paramètre
     */
    public SourceEnergie getEnergie(String nomEnergie) {
        return listEnergie.get(nomEnergie);
    }
    
	/**
     * Récupérer le nombre de pièces du calculateur
     * @return Le nombre de pièce
     */
    public int getNbPiece() {
        return nbPiece;
    }
    
	/**
     * Changer le nombre de pièce du calculateur
     * @param n Nombre de pièce
     */
    public void setNbPiece(int n) {
        nbPiece = n;
    }
    
	/**
     * Vérifie chaque paramètre du calculateur
     * Exécute un thread
     * @return True sur l'opération s'est bien passé
     */
    public boolean verifierParam() {
		final Thread t = new Thread(this);
		t.start();
		return true;
	}
	
	/**
     * Fonction thread appelé par verifierParam
     * Fonction du thread
     * Vérifie chaques paramètres du calculateur
     */
	public void run() {
        int i = 0, j=0;
        boolean b =false;
        String presence = "presence_";
        String temperature = "temperature_";
        while(true) {
            //verifier piece par piece
            for(i=0; i<nbPiece; i++) {
                presence = presence + String.valueOf(i+1);
                temperature = temperature + String.valueOf(i+1);
                
                //verifier presence
               //System.out.println(presence + " : " + getCapteur(presence));
                if(getCapteur(presence).getValeurParam()==1)
                    b = true;
                traitement_presence(b,i+1);
                
                //verifier temperature
                if(getCapteur(temperature).getValeurParam() > getCapteur(temperature).getPiece().getTemperatureVoulu())
                    j=1;
                if(getCapteur(temperature).getValeurParam() < getCapteur(temperature).getPiece().getTemperatureVoulu())
                    j=-1;
                traitement_temperature(j,i+1);
                
                j=0;
                b=false;
                presence = "presence_";
                temperature = "temperature_";
            }
            //verifier electricite
            traitement_electricite();
        }
    }
    
	/**
     * Fonction appelé par le thread
     * Traitement des cas de présences ou non pour la pièce i
     * @param b Présence dans la pièce
     * @param p Numéro de la pièce
     * @return Résultat de l'éxecution
     */
    private boolean traitement_presence(boolean b, int p) {
        boolean ret = true ;
        String lampe = "lampe_" + String.valueOf(p);
        String lumiere = "lumiere_" + String.valueOf(p);

        //si personne
        if(!b) {
            if(getObjet(lampe).getEtat() && !getObjet(lampe).getVerrou()) 
                ret = getObjet(lampe).modifierEtat();
            if(getCapteur(lumiere).getValeurParam() == 1)
                ret = ret && getCapteur(lumiere).modifierVar();
            return ret;
        }
        
        String volet = "volet_" + String.valueOf(p);
        //si presence et jour
        if(getCapteur("luminositeExt").getValeurParam() == 1) {
            if(!getObjet(volet).getEtat() && !getObjet(volet).getVerrou())
                ret = getObjet(volet).modifierEtat();
            if(getObjet(lampe).getEtat() && !getObjet(lampe).getVerrou())
                ret = ret && getObjet(lampe).modifierEtat();
            if(getCapteur(lumiere).getValeurParam() != 1)
                ret = ret && getCapteur(lumiere).modifierVar();
            return ret;
        }
        
        //si presence et nuit
        if(getObjet(volet).getEtat() && !getObjet(volet).getVerrou())
            ret = getObjet(volet).modifierEtat();
        if(!getObjet(lampe).getEtat() && !getObjet(lampe).getVerrou())
            ret = ret && getObjet(lampe).modifierEtat();
        if(getCapteur(lumiere).getValeurParam() != 1)
            ret = ret && getCapteur(lumiere).modifierVar();
        return ret;
    }
    
	/**
     * Fonction appelé par le thread
     * Traitement des cas temperature >, = ou < a celle voulu pour la piece p
     * @param t Température de la pièce
     * @param p Numéro de la pièce
     * @return Résultat de l'éxecution
     */
    private boolean traitement_temperature(int t, int p) {
        boolean ret = true;
        String fenetre = "fenetre_" + String.valueOf(p);
        String radiateur = "radiateur_" + String.valueOf(p);
        
        //temperature ideal
        if(t==0) {
            if(getObjet(radiateur).getEtat() && !getObjet(radiateur).getVerrou())
                ret = ret && getObjet(radiateur).modifierEtat();
            if(getObjet(fenetre).getEtat() && !getObjet(fenetre).getVerrou())
                ret = ret && getObjet(fenetre).modifierEtat();
            return ret;
        }
        
        String temperature = "temperature_" + String.valueOf(p);
        
        //temperature superieur a voulu
        if(t==1) {
            if(getObjet(radiateur).getEtat() && !getObjet(radiateur).getVerrou())
                ret = ret && getObjet(radiateur).modifierEtat();
            if(getCapteur("temperatureExt").getValeurParam() > getCapteur(temperature).getValeurParam()) {
                if(getObjet(fenetre).getEtat())
                    ret = ret && getObjet(fenetre).modifierEtat();
            }
            else
                if(!getObjet(fenetre).getEtat() && !getObjet(fenetre).getVerrou())
                    ret = ret && getObjet(fenetre).modifierEtat();
            getCapteur(temperature).modifierVar();
            return ret;
        }
        
        //temperature inferieur a voulu
        if(getCapteur("temperatureExt").getValeurParam() > getCapteur(temperature).getValeurParam()) {
            if(getObjet(radiateur).getEtat() && !getObjet(radiateur).getVerrou())
                ret = ret && getObjet(radiateur).modifierEtat();
            if(!getObjet(fenetre).getEtat() && !getObjet(fenetre).getVerrou())
                ret = ret && getObjet(fenetre).modifierEtat();
        }
        else {
            if(!getObjet(radiateur).getEtat() && !getObjet(radiateur).getVerrou())
                ret = ret && getObjet(radiateur).modifierEtat();
            if(getObjet(fenetre).getEtat() && !getObjet(fenetre).getVerrou())
                ret = ret && getObjet(fenetre).modifierEtat();
        }
        getCapteur(temperature).modifierVar();
        return ret;
    }
    
	/**
     * Fonction appelé par le thread
     * Traitement des besoin d'electricite
     * @return Résultat de l'éxecution
     */
    private boolean traitement_electricite() {
        boolean reseau = true;
        boolean ret = true;
        if(getCapteur("ventExt").getValeurParam() == 1) {
            reseau = false;
            if(!getEnergie("eolienne").getEtat())
                ret = ret && getEnergie("eolienne").modifierEtat();
        }
        
        if(getCapteur("luminositeExt").getValeurParam() == 1) {
            reseau = false;
            if(!getEnergie("solaire").getEtat())
                ret = ret && getEnergie("solaire").modifierEtat();
        }
        
        if(reseau)
            if(!getEnergie("reseau").getEtat())
                ret = ret && getEnergie("reseau").modifierEtat();
        
        return ret;
    }
}